package me.goldze.mvvmhabit.base;

import android.annotation.SuppressLint;
import android.app.Application;
import android.os.Bundle;
import android.os.Handler;

import com.trello.rxlifecycle2.LifecycleProvider;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

import androidx.annotation.NonNull;
import androidx.databinding.ObservableBoolean;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import me.goldze.mvvmhabit.bus.event.SingleLiveEvent;
import me.goldze.mvvmhabit.service.IRfidEvent;
import me.goldze.mvvmhabit.utils.KLog;
import me.goldze.mvvmhabit.utils.cache.ACache;
import me.goldze.mvvmhabit.utils.cache.AKey;

/**
 * Created by goldze on 2017/6/15.
 */
public class BaseViewModel<M extends BaseModel> extends AndroidViewModel implements IBaseViewModel, Consumer<Disposable> {
    protected M model;
    private UIChangeLiveData uc;
    //弱引用持有
    private WeakReference<LifecycleProvider> lifecycle;
    //管理RxJava，主要针对RxJava异步操作造成的内存泄漏
    private CompositeDisposable mCompositeDisposable;

    public ObservableBoolean isReading = new ObservableBoolean(false);

    public BaseViewModel(@NonNull Application application) {
        this(application, null);
    }

    public BaseViewModel(@NonNull Application application, M model) {
        super(application);
        this.model = model;
        mCompositeDisposable = new CompositeDisposable();
    }

    private IRfidEvent rfidEvent;

    public void registerRFID(IRfidEvent rfidEvent) {
        this.rfidEvent = rfidEvent;
    }

    protected void addSubscribe(Disposable disposable) {
        if (mCompositeDisposable == null) {
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(disposable);
    }

    /**
     * 注入RxLifecycle生命周期
     *
     * @param lifecycle
     */
    public void injectLifecycleProvider(LifecycleProvider lifecycle) {
        this.lifecycle = new WeakReference<>(lifecycle);
    }


    public LifecycleProvider getLifecycleProvider() {
        return lifecycle.get();
    }

    public UIChangeLiveData getUC() {
        if (uc == null) {
            uc = new UIChangeLiveData();
        }
        return uc;
    }


    public void onError(String errorInfo) {
        uc.onErrorEvent.postValue(errorInfo);
    }

    public void showLoadingDialog() {
        showLoadingDialog("请稍后...");
    }

    public void showLoadingDialog(String title) {
        uc.showLoadingEvent.postValue(title);
    }

    public void dismissLodingDialog() {
        uc.dismissLoadingEvent.call();
    }

    public void showErrorDialog(String title) {
        uc.onErrorEvent.postValue(title);
    }

    public void dismissErrorDialog() {
        uc.onErrorEvent.call();
    }


    /**
     * 跳转页面
     *
     * @param clz 所跳转的目的Activity类
     */
    public void startActivity(Class<?> clz) {
        startActivity(clz, null);
    }

    /**
     * 跳转页面
     *
     * @param clz    所跳转的目的Activity类
     * @param bundle 跳转所携带的信息
     */
    public void startActivity(Class<?> clz, Bundle bundle) {
        Map<String, Object> params = new HashMap<>();
        params.put(ParameterField.CLASS, clz);
        if (bundle != null) {
            params.put(ParameterField.BUNDLE, bundle);
        }
        uc.startActivityEvent.postValue(params);
    }

    /**
     * 跳转容器页面
     *
     * @param canonicalName 规范名 : Fragment.class.getCanonicalName()
     */
    public void startContainerActivity(String canonicalName) {
        startContainerActivity(canonicalName, null);
    }

    /**
     * 跳转容器页面
     *
     * @param canonicalName 规范名 : Fragment.class.getCanonicalName()
     * @param bundle        跳转所携带的信息
     */
    public void startContainerActivity(String canonicalName, Bundle bundle) {
        Map<String, Object> params = new HashMap<>();
        params.put(ParameterField.CANONICAL_NAME, canonicalName);
        if (bundle != null) {
            params.put(ParameterField.BUNDLE, bundle);
        }
        uc.startContainerActivityEvent.postValue(params);
    }

    /**
     * 关闭界面
     */
    public void finish() {
        uc.finishEvent.call();
    }

    public void finishActivity() {
        uc.finishActivityEvent.call();
    }




    /**
     * 返回上一层
     */
    public void onBackPressed() {
        uc.onBackPressedEvent.call();
    }

    @Override
    public void onAny(LifecycleOwner owner, Lifecycle.Event event) {
    }

    @Override
    public void onCreate() {
    }

    @Override
    public void onDestroy() {
    }

    @Override
    public void onStart() {
    }

    @Override
    public void onStop() {
    }

    @Override
    public void onResume() {
    }

    @Override
    public void onPause() {
    }

    //    Disposable subscribe;



    @Override
    public void registerRxBus() {

    }

    @Override
    public void removeRxBus() {

    }

    @Override
    protected void onCleared() {
        super.onCleared();
        if (model != null) {
            model.onCleared();
        }
        //ViewModel销毁时会执行，同时取消所有异步任务
        if (mCompositeDisposable != null) {
            mCompositeDisposable.clear();
        }
    }

    @Override
    public void accept(Disposable disposable) throws Exception {
        KLog.e("执行addSubscribe");
        addSubscribe(disposable);
    }




    public final class UIChangeLiveData extends SingleLiveEvent {
        private SingleLiveEvent<String> showLoadingEvent;
        private SingleLiveEvent<Void> dismissLoadingEvent;
        private SingleLiveEvent<Map<String, Object>> startActivityEvent;
        private SingleLiveEvent<Map<String, Object>> startContainerActivityEvent;
        private SingleLiveEvent<Void> finishEvent;
        private SingleLiveEvent<Void> finishActivityEvent;
        private SingleLiveEvent<Void> onBackPressedEvent;
        private SingleLiveEvent<Void> hideKeyboardEvent;
        private SingleLiveEvent<String> onErrorEvent;

        private SingleLiveEvent<Void> refreshEvent;
        private SingleLiveEvent<Void> removeFragmentEvent;

        private SingleLiveEvent<Void> showRobotLoadingEvent;
        private SingleLiveEvent<Void> hideRobotLoadingEvent;

        public SingleLiveEvent<Void> getShowRobotLoadingEvent() {
            return showRobotLoadingEvent = createLiveData(showRobotLoadingEvent);
        }

        public SingleLiveEvent<Void> getHideRobotLoadingEvent() {
            return hideRobotLoadingEvent = createLiveData(hideRobotLoadingEvent);
        }

        public SingleLiveEvent<Void> getRefreshEvent() {
            return refreshEvent = createLiveData(refreshEvent);
        }

        public SingleLiveEvent<String> getShowLoadingEvent() {
            return showLoadingEvent = createLiveData(showLoadingEvent);
        }

        public SingleLiveEvent<Void> getDismissLoadingEvent() {
            return dismissLoadingEvent = createLiveData(dismissLoadingEvent);
        }

        public SingleLiveEvent<Void> getRemoveFragmentEvent() {
            return removeFragmentEvent = createLiveData(removeFragmentEvent);
        }

        public SingleLiveEvent<Map<String, Object>> getStartActivityEvent() {
            return startActivityEvent = createLiveData(startActivityEvent);
        }

        public SingleLiveEvent<Map<String, Object>> getStartContainerActivityEvent() {
            return startContainerActivityEvent = createLiveData(startContainerActivityEvent);
        }

        public SingleLiveEvent<Void> getFinishEvent() {
            return finishEvent = createLiveData(finishEvent);
        }

        public SingleLiveEvent<Void> getFinishActivityEvent() {
            return finishActivityEvent = createLiveData(finishActivityEvent);
        }

        public SingleLiveEvent<Void> getOnBackPressedEvent() {
            return onBackPressedEvent = createLiveData(onBackPressedEvent);
        }

        private <T> SingleLiveEvent<T> createLiveData(SingleLiveEvent<T> liveData) {
            if (liveData == null) {
                liveData = new SingleLiveEvent<>();
            }
            return liveData;
        }

        @Override
        public void observe(LifecycleOwner owner, Observer observer) {
            super.observe(owner, observer);
        }

        public SingleLiveEvent<String> getOnError() {
            return onErrorEvent = createLiveData(onErrorEvent);
        }

        public SingleLiveEvent<Void> getHideKeyboardEvent() {
            return hideKeyboardEvent = createLiveData(hideKeyboardEvent);
        }
    }

    public static final class ParameterField {
        public static String CLASS = "CLASS";
        public static String CANONICAL_NAME = "CANONICAL_NAME";
        public static String BUNDLE = "BUNDLE";
    }
//    ==================下面是接口实现部分，不需要处理===============================

    public void registerEvent(String key) {
        new Handler().postDelayed(() -> {
            if (rfidEvent!=null) {
                System.out.println("订阅第1步：延迟300毫秒 [ "+key+" ]");
                rfidEvent.registerEvent(key);
                if (ACache.getInstance().getAsBoolean(AKey.AUTO_SCAN_ON_FRAGMENT_OPEN)){
                    System.out.println(key+"： 开启自动扫描");
                    rfidEvent.autoScan();
                }
            }
        },300);
    }

    public void removeEvent() {
        if (rfidEvent!=null)
            rfidEvent.removeEvent();
    }



    public void changeScanState() {
        if (rfidEvent!=null)
            rfidEvent.changeScanState();
    }


    public void cleanRFIDCache() {
        if (rfidEvent!=null)
         rfidEvent.cleanRFIDCache();
    }

    public void cleanRFIDCache(String key){
        if (rfidEvent!=null)
            rfidEvent.cleanRFIDCache(key);
    }

    public void cleanRFIDCacheNotStop(){
        if (rfidEvent!=null)
            rfidEvent.cleanRFIDCacheNotStop();
    }

    public void stopScan() {
        if (rfidEvent!=null)
         rfidEvent.stopScan();
    }

    public String getCacheKey() {
        if (rfidEvent==null)
            return "";
        return rfidEvent.getCacheKey();
    }

    public void playOtherSound(){
        if (rfidEvent!=null)
         rfidEvent.playOtherSound();
    }
}
